package com.coder.rental.security;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.convert.NumberWithFormat;
import cn.hutool.core.date.DateTime;
import cn.hutool.jwt.JWTPayload;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.coder.rental.entity.User;
import com.coder.rental.utils.JwtUtils;
import com.coder.rental.utils.RedisUtils;
import com.coder.rental.utils.ResultCode;
import jakarta.annotation.Resource;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

/**
 * @author caelan
 * @project auto_rental
 */
/*      这段代码的主要功能是：
        在用户登录成功后
        将用户信息转换为 JSON 格式
        通过 HTTP 响应返回给客户端
*/
@Component
public class LoginSucdessHandler implements AuthenticationSuccessHandler {

    @Resource
    private RedisUtils redisUtils;

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
                                        Authentication authentication) throws IOException, ServletException {
        //设置客户端的响应的内容类型是json
        response.setContentType("application/json;charset=utf-8");
        //获取认证主体，即登录用户
        User user = (User)authentication.getPrincipal();

        //生成token的处理，实际项目中通常在这里生成Token并返回给客户端
        Map<String,Object> map = new HashMap<>();
        map.put("username",user.getUsername());
        map.put("userid",user.getId());
        String token = JwtUtils.createToken(map);

        //解析token获取过期时间，并构建认证结果对象
        NumberWithFormat claim = (NumberWithFormat) JwtUtils.parseToken(token)
                .getClaim(JWTPayload.EXPIRES_AT);
        long expireTime = Convert.toDate(claim).getTime();
        AuthenticationResult authenticationResult
                = new AuthenticationResult(user.getId(), ResultCode.SUCCESS,
                token,expireTime);


        //获取一个结果
        String result= JSON.toJSONString(authenticationResult,
                SerializerFeature.DisableCircularReferenceDetect);//禁用循环引用检测，避免对象中存在循环引用时出现问题

        //获取输出流,向客户端发送认证结果
        ServletOutputStream outputStream = response.getOutputStream();//获取响应输出流
        outputStream.write(result.getBytes(StandardCharsets.UTF_8));//将 JSON 字符串转换为 UTF-8 字节数组并写入输出流
        outputStream.flush();
        outputStream.close();//刷新并关闭流（确保所有数据发送到客户端）

        // 将token存入redis，设置过期时间
        String tokenKey = "token:"+token;
        long nowTime = DateTime.now().getTime();
        redisUtils.set(tokenKey,token,(expireTime-nowTime)/1000);


    }
}
